export function assign<T>(def = {}, origin = {}): T {
  return Object.assign({}, def, origin) as T
}

export function noop() {}

/**
 * 获取数据类型
 *
 * getType([]) -> "[object Array]"
 *
 * @param target
 * @returns {string}
 */
export function toRawType (target) {
  return Object.prototype.toString.call(target)
}

/**
 * 获取对象的数据类型
 *
 * getType([]) -> "array"
 *
 * @param { any } target 目标对象
 * @returns {string}
 */
export function getType (target) {
  return toRawType(target).slice(8, -1).toLowerCase()
}

/**
 * 获取对象的数据类型
 *
 * getType([], "array") -> true
 *
 * @param { any } target 目标对象
 * @param { string } type 目标类型
 * @returns { boolean }
 */
export function isType (target: any, type: string) {
  return getType(target) === type
}

/**
 * 获取对象的数据类型
 *
 * getType([], "array") -> true
 *
 * @param { any } target 目标对象
 * @param { string[] } types 目标类型
 * @returns { boolean }
 */
export function inTypes (target: any, types: string[]) {
  const type = getType(target)
  return types.includes(type)
}

/**
 * 是否是 String 类型
 *
 * getType([]) -> false
 *
 * @param { any } target 目标对象
 * @returns { boolean }
 */
export function isString (target: any) {
  return getType(target) === 'string'
}

/**
 * 是否是 Object 类型
 *
 * getType([]) -> false
 *
 * @param { any } target 目标对象
 * @returns { boolean }
 */
export function isObject (target: any) {
  return getType(target) === 'object'
}

/**
 * 是否是 Array 类型
 *
 * getType([]) -> true
 *
 * @param { any } target 目标对象
 * @returns { boolean }
 */
export function isArray (target: any) {
  return getType(target) === 'array'
}

/**
 * 获取查询字符串
 *
 * @param url
 * @param isToLowerString
 */
export function analysisQueryString (url = window.location.href, isToLowerString = false) {
  let search = url.substring(url.lastIndexOf('?') + 1);
  const searchString = isToLowerString ? search.toLowerCase() : search
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;

  searchString.replace(reg, (str, $1, $2) => {
    const key = decodeURIComponent($1);
    obj[key] = decodeURIComponent($2) + '';
    return str
  });

  return obj
}

/**
 * 检查 是否是 HTML 元素
 *
 * @param element
 * @returns {boolean}
 */
export function isHTMLElement(element) {
  try {
    return !!element.cloneNode(true) && element instanceof HTMLElement;
  } catch (e) {
    return false;
  }
}

/**
 * 设置样式
 *
 * @param element
 * @param cssObj
 */
export function setStyle(element, cssObj) {
  if (isHTMLElement(element)) {
    Object.keys(cssObj || {}).forEach(function (key) {
      element.style[key] = cssObj[key];
    })
  } else {
    console.error(`${ element } is not HTMLElement!`)
  }
}

/**
 * 创建 html
 *
 * @param element
 * @param attrs
 * @param children
 * @returns {any}
 */
export function createElement(element, attrs?, children?) {
  const elementNode = document.createElement(element);

  if (attrs && typeof attrs === 'object') {
    for (let key in attrs) {
      if (key === 'style' && isType(attrs[key], 'object')) {
        setStyle(elementNode, attrs['style']);
      } else {
        elementNode.setAttribute(key, attrs[key])
      }
    }
  }

  if (Array.isArray(children)) {
    children.forEach(function (child) {
      if (isHTMLElement(child)) {
        elementNode.appendChild(child)
      }
    })
  }

  return elementNode
}

/**
 * 创建 Media DOM
 *
 * @param type 类型
 * @param attrs 属性
 */
export function createMediaElement(type: string, attrs = {}) {
  return createElement(type, {
    autoplay: true,
    controls: true,
    muted: false,
    ...attrs
  });
}

/**
 * 判断当前节点是父节点的直接子节点
 * @param parentNode
 * @param childNode
 */
export function hasChild(parentNode, childNode) {
  return (
    isHTMLElement(parentNode) &&
    isHTMLElement(childNode) &&
    parentNode.contains(childNode) &&
    childNode.parentNode === parentNode
  )
}
